home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / xybots.c < prev    next >
C/C++ Source or Header  |  2000-04-04  |  14KB  |  542 lines

  1. /***************************************************************************
  2.  
  3.   vidhrdw/xybots.c
  4.  
  5.   Functions to emulate the video hardware of the machine.
  6.  
  7. ****************************************************************************
  8.  
  9.     Playfield encoding
  10.     ------------------
  11.         1 16-bit word is used
  12.  
  13.         Word 1:
  14.             Bit  15    = horizontal flip
  15.             Bits 12-14 = color
  16.             Bits  0-11 = image
  17.  
  18.  
  19.     Motion Object encoding
  20.     ----------------------
  21.         4 16-bit words are used
  22.  
  23.         Word 1:
  24.             Bits  0-13 = index of the image (0-16384)
  25.             Bit  15    = horizontal flip
  26.  
  27.         Word 2:
  28.             Bits  0-3  = priority
  29.  
  30.         Word 3:
  31.             Bits  0-2  = height of the sprite / 8 (ranges from 1-8)
  32.             Bits  7-14 = Y position of the sprite
  33.  
  34.         Word 4:
  35.             Bits  0-3  = image palette
  36.             Bits  7-14 = X position of the sprite
  37.  
  38.  
  39.     Alpha layer encoding
  40.     --------------------
  41.         1 16-bit word is used
  42.  
  43.         Word 1:
  44.             Bit  15    = transparent/opaque
  45.             Bit  10-13 = color
  46.             Bits  0-9  = index of the character
  47.  
  48. ***************************************************************************/
  49.  
  50.  
  51. #include "driver.h"
  52. #include "machine/atarigen.h"
  53. #include "vidhrdw/generic.h"
  54.  
  55. #define XCHARS 42
  56. #define YCHARS 30
  57.  
  58. #define XDIM (XCHARS*8)
  59. #define YDIM (YCHARS*8)
  60.  
  61.  
  62.  
  63. /*************************************
  64.  *
  65.  *    Structures
  66.  *
  67.  *************************************/
  68.  
  69. struct pf_overrender_data
  70. {
  71.     struct osd_bitmap *bitmap;
  72.     int mo_priority;
  73. };
  74.  
  75.  
  76.  
  77. /*************************************
  78.  *
  79.  *    Prototypes
  80.  *
  81.  *************************************/
  82.  
  83. static const UINT8 *update_palette(void);
  84.  
  85. static void pf_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  86. static void pf_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  87. static void pf_check_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  88. static void pf_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  89.  
  90. static void mo_color_callback(const UINT16 *data, const struct rectangle *clip, void *param);
  91. static void mo_render_callback(const UINT16 *data, const struct rectangle *clip, void *param);
  92.  
  93.  
  94.  
  95. /*************************************
  96.  *
  97.  *    Video system start
  98.  *
  99.  *************************************/
  100.  
  101. int xybots_vh_start(void)
  102. {
  103.     static struct atarigen_mo_desc mo_desc =
  104.     {
  105.         64,                  /* maximum number of MO's */
  106.         8,                   /* number of bytes per MO entry */
  107.         2,                   /* number of bytes between MO words */
  108.         0,                   /* ignore an entry if this word == 0xffff */
  109.         -1, 0, 0x3f,         /* link = (data[linkword] >> linkshift) & linkmask */
  110.         0                    /* render in reverse link order */
  111.     };
  112.  
  113.     static struct atarigen_pf_desc pf_desc =
  114.     {
  115.         8, 8,                /* width/height of each tile */
  116.         64, 64,                /* number of tiles in each direction */
  117.         1                    /* non-scrolling */
  118.     };
  119.  
  120.     /* initialize the playfield */
  121.     if (atarigen_pf_init(&pf_desc))
  122.         return 1;
  123.  
  124.     /* initialize the motion objects */
  125.     if (atarigen_mo_init(&mo_desc))
  126.     {
  127.         atarigen_pf_free();
  128.         return 1;
  129.     }
  130.  
  131.     return 0;
  132. }
  133.  
  134.  
  135.  
  136. /*************************************
  137.  *
  138.  *    Video system shutdown
  139.  *
  140.  *************************************/
  141.  
  142. void xybots_vh_stop(void)
  143. {
  144.     atarigen_pf_free();
  145.     atarigen_mo_free();
  146. }
  147.  
  148.  
  149.  
  150. /*************************************
  151.  *
  152.  *    Playfield RAM write handler
  153.  *
  154.  *************************************/
  155.  
  156. WRITE_HANDLER( xybots_playfieldram_w )
  157. {
  158.     int oldword = READ_WORD(&atarigen_playfieldram[offset]);
  159.     int newword = COMBINE_WORD(oldword, data);
  160.  
  161.     if (oldword != newword)
  162.     {
  163.         WRITE_WORD(&atarigen_playfieldram[offset], newword);
  164.         atarigen_pf_dirty[offset / 2] = 1;
  165.     }
  166. }
  167.  
  168.  
  169.  
  170. /*************************************
  171.  *
  172.  *    Periodic scanline updater
  173.  *
  174.  *************************************/
  175.  
  176. void xybots_scanline_update(int scanline)
  177. {
  178.     if (scanline < YDIM)
  179.         atarigen_mo_update(atarigen_spriteram, 0, scanline);
  180. }
  181.  
  182.  
  183.  
  184. /*************************************
  185.  *
  186.  *    Main refresh
  187.  *
  188.  *************************************/
  189.  
  190. void xybots_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh)
  191. {
  192.     int i;
  193.  
  194.     /* update the palette */
  195.     if (update_palette())
  196.         memset(atarigen_pf_dirty, 1, atarigen_playfieldram_size / 2);
  197.  
  198.     /* set up the all-transparent overrender palette */
  199.     for (i = 0; i < 16; i++)
  200.         atarigen_overrender_colortable[i] = palette_transparent_pen;
  201.  
  202.     /* render the playfield */
  203.     atarigen_pf_process(pf_render_callback, bitmap, &Machine->drv->visible_area);
  204.  
  205.     /* render the motion objects */
  206.     atarigen_mo_process(mo_render_callback, bitmap);
  207.  
  208.     /* redraw the alpha layer completely */
  209.     {
  210.         const struct GfxElement *gfx = Machine->gfx[2];
  211.         int sx, sy, offs;
  212.  
  213.         for (sy = 0; sy < YCHARS; sy++)
  214.             for (sx = 0, offs = sy * 64; sx < XCHARS; sx++, offs++)
  215.             {
  216.                 int data = READ_WORD(&atarigen_alpharam[offs * 2]);
  217.                 int code = data & 0x3ff;
  218.                 int opaque = data & 0x8000;
  219.  
  220.                 if (code || opaque)
  221.                 {
  222.                     int color = (data >> 12) & 7;
  223.  
  224.                     drawgfx(bitmap, gfx, code, color, 0, 0, 8 * sx, 8 * sy, 0,
  225.                             opaque ? TRANSPARENCY_NONE : TRANSPARENCY_PEN, 0);
  226.                 }
  227.             }
  228.     }
  229.  
  230.     /* update onscreen messages */
  231.     atarigen_update_messages();
  232. }
  233.  
  234.  
  235.  
  236. /*************************************
  237.  *
  238.  *    Palette management
  239.  *
  240.  *************************************/
  241.  
  242. static const UINT8 *update_palette(void)
  243. {
  244.     UINT16 mo_map[48], al_map[8], pf_map[16];
  245.     int i, j;
  246.  
  247.     /* reset color tracking */
  248.     memset(mo_map, 0, sizeof(mo_map));
  249.     memset(pf_map, 0, sizeof(pf_map));
  250.     memset(al_map, 0, sizeof(al_map));
  251.     palette_init_used_colors();
  252.  
  253.     /* update color usage for the playfield */
  254.     atarigen_pf_process(pf_color_callback, pf_map, &Machine->drv->visible_area);
  255.  
  256.     /* update color usage for the mo's */
  257.     atarigen_mo_process(mo_color_callback, mo_map);
  258.  
  259.     /* update color usage for the alphanumerics */
  260.     {
  261.         const unsigned int *usage = Machine->gfx[2]->pen_usage;
  262.         int sx, sy, offs;
  263.  
  264.         for (sy = 0; sy < YCHARS; sy++)
  265.             for (sx = 0, offs = sy * 64; sx < XCHARS; sx++, offs++)
  266.             {
  267.                 int data = READ_WORD(&atarigen_alpharam[offs * 2]);
  268.                 int color = (data >> 12) & 7;
  269.                 int code = data & 0x3ff;
  270.                 al_map[color] |= usage[code];
  271.             }
  272.     }
  273.  
  274.     /* rebuild the playfield palette */
  275.     for (i = 0; i < 16; i++)
  276.     {
  277.         UINT16 used = pf_map[i];
  278.         if (used)
  279.             for (j = 0; j < 16; j++)
  280.                 if (used & (1 << j))
  281.                     palette_used_colors[0x200 + i * 16 + j] = PALETTE_COLOR_USED;
  282.     }
  283.  
  284.     /* rebuild the motion object palette */
  285.     for (i = 0; i < 48; i++)
  286.     {
  287.         UINT16 used = mo_map[i];
  288.         if (used)
  289.         {
  290.             palette_used_colors[0x100 + i * 16 + 0] = PALETTE_COLOR_TRANSPARENT;
  291.             for (j = 1; j < 16; j++)
  292.                 if (used & (1 << j))
  293.                     palette_used_colors[0x100 + i * 16 + j] = PALETTE_COLOR_USED;
  294.         }
  295.     }
  296.  
  297.     /* rebuild the alphanumerics palette */
  298.     for (i = 0; i < 8; i++)
  299.     {
  300.         UINT16 used = al_map[i];
  301.         if (used)
  302.             for (j = 0; j < 4; j++)
  303.                 if (used & (1 << j))
  304.                     palette_used_colors[0x000 + i * 4 + j] = PALETTE_COLOR_USED;
  305.     }
  306.  
  307.     return palette_recalc();
  308. }
  309.  
  310.  
  311.  
  312. /*************************************
  313.  *
  314.  *    Playfield palette
  315.  *
  316.  *************************************/
  317.  
  318. static void pf_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  319. {
  320.     const unsigned int *usage = Machine->gfx[0]->pen_usage;
  321.     UINT16 *colormap = param;
  322.     int x, y;
  323.  
  324.     /* standard loop over tiles */
  325.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  326.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  327.         {
  328.             int offs = y * 64 + x;
  329.             int data = READ_WORD(&atarigen_playfieldram[offs * 2]);
  330.             int color = (data >> 11) & 15;
  331.             int code = data & 0x1fff;
  332.  
  333.             /* mark the colors used by this tile */
  334.             colormap[color] |= usage[code];
  335.         }
  336. }
  337.  
  338.  
  339.  
  340. /*************************************
  341.  *
  342.  *    Playfield rendering
  343.  *
  344.  *************************************/
  345.  
  346. static void pf_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  347. {
  348.     const struct GfxElement *gfx = Machine->gfx[0];
  349.     struct osd_bitmap *bitmap = param;
  350.     int x, y;
  351.  
  352.     /* standard loop over tiles */
  353.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  354.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  355.         {
  356.             int offs = y * 64 + x;
  357.  
  358.             /* update only if dirty */
  359.             if (atarigen_pf_dirty[offs])
  360.             {
  361.                 int data = READ_WORD(&atarigen_playfieldram[offs * 2]);
  362.                 int color = (data >> 11) & 15;
  363.                 int hflip = data & 0x8000;
  364.                 int code = data & 0x1fff;
  365.  
  366.                 drawgfx(atarigen_pf_bitmap, gfx, code, color, hflip, 0, 8 * x, 8 * y, 0, TRANSPARENCY_NONE, 0);
  367.                 atarigen_pf_dirty[offs] = 0;
  368.             }
  369.         }
  370.  
  371.     /* then blast the result */
  372.     copybitmap(bitmap, atarigen_pf_bitmap, 0, 0, 0, 0, clip, TRANSPARENCY_NONE, 0);
  373. }
  374.  
  375.  
  376.  
  377. /*************************************
  378.  *
  379.  *    Playfield overrender check
  380.  *
  381.  *************************************/
  382.  
  383. static void pf_check_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  384. {
  385.     struct pf_overrender_data *overrender_data = param;
  386.     int mo_priority = overrender_data->mo_priority;
  387.     int x, y;
  388.  
  389.     /* if we've already decided, bail */
  390.     if (mo_priority == -1)
  391.         return;
  392.  
  393.     /* standard loop over tiles */
  394.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  395.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  396.         {
  397.             int offs = y * 64 + x;
  398.             int data = READ_WORD(&atarigen_playfieldram[offs * 2]);
  399.             int color = (data >> 11) & 15;
  400.  
  401.             /* this is the priority equation from the schematics */
  402.             if (mo_priority > color)
  403.             {
  404.                 overrender_data->mo_priority = -1;
  405.                 return;
  406.             }
  407.         }
  408. }
  409.  
  410.  
  411.  
  412. /*************************************
  413.  *
  414.  *    Playfield overrendering
  415.  *
  416.  *************************************/
  417.  
  418. static void pf_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  419. {
  420.     const struct pf_overrender_data *overrender_data = param;
  421.     const struct GfxElement *gfx = Machine->gfx[0];
  422.     struct osd_bitmap *bitmap = overrender_data->bitmap;
  423.     int mo_priority = overrender_data->mo_priority;
  424.     int x, y;
  425.  
  426.     /* standard loop over tiles */
  427.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  428.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  429.         {
  430.             int offs = y * 64 + x;
  431.             int data = READ_WORD(&atarigen_playfieldram[offs * 2]);
  432.             int color = (data >> 11) & 15;
  433.  
  434.             /* this is the priority equation from the schematics */
  435.             if (mo_priority > color)
  436.             {
  437.                 int hflip = data & 0x8000;
  438.                 int code = data & 0x1fff;
  439.  
  440.                 drawgfx(bitmap, gfx, code, color, hflip, 0, 8 * x, 8 * y, clip, TRANSPARENCY_NONE, 0);
  441.             }
  442.         }
  443. }
  444.  
  445.  
  446.  
  447. /*************************************
  448.  *
  449.  *    Motion object palette
  450.  *
  451.  *************************************/
  452.  
  453. static void mo_color_callback(const UINT16 *data, const struct rectangle *clip, void *param)
  454. {
  455.     const unsigned int *usage = Machine->gfx[1]->pen_usage;
  456.     UINT16 *colormap = param;
  457.     int code = data[0] & 0x3fff;
  458.     int color = data[3] & 7;
  459.     int vsize = (data[2] & 7) + 1;
  460.     UINT16 temp = 0;
  461.     int i;
  462.  
  463.     /* sneaky -- an extra color bank is hidden after the playfield palette */
  464.     if (data[3] & 8) color = 0x20 + (color ^ 7);
  465.  
  466.     for (i = 0; i < vsize; i++)
  467.         temp |= usage[code++];
  468.     colormap[color] |= temp;
  469. }
  470.  
  471.  
  472.  
  473. /*************************************
  474.  *
  475.  *    Motion object rendering
  476.  *
  477.  *************************************/
  478.  
  479. static void mo_render_callback(const UINT16 *data, const struct rectangle *clip, void *param)
  480. {
  481.     struct GfxElement *gfx = Machine->gfx[1];
  482.     struct pf_overrender_data overrender_data;
  483.     struct osd_bitmap *bitmap = param;
  484.     struct rectangle pf_clip;
  485.  
  486.     /* extract data from the various words */
  487.     int code = data[0] & 0x3fff;
  488.     int hflip = data[0] & 0x8000;
  489.     int priority = ~data[1] & 15;
  490.     int vsize = (data[2] & 7) + 1;
  491.     int ypos = -(data[2] >> 7);
  492.     int color = data[3] & 7;
  493.     int xpos = data[3] >> 7;
  494.  
  495.     /* sneaky -- an extra color bank is hidden after the playfield palette */
  496.     if (data[3] & 8) color = 0x20 + (color ^ 7);
  497.  
  498.     /* adjust for the height */
  499.     ypos -= vsize * 8;
  500.  
  501.     /* adjust the final coordinates */
  502.     xpos &= 0x1ff;
  503.     ypos &= 0x1ff;
  504.     if (xpos >= XDIM) xpos -= 0x200;
  505.     if (ypos >= YDIM) ypos -= 0x200;
  506.  
  507.     /* clip the X coordinate */
  508.     if (xpos <= -8 || xpos >= XDIM)
  509.         return;
  510.  
  511.     /* determine the bounding box */
  512.     atarigen_mo_compute_clip_8x8(pf_clip, xpos, ypos, 1, vsize, clip);
  513.  
  514.     /* see if we need to overrender */
  515.     overrender_data.mo_priority = priority;
  516.     atarigen_pf_process(pf_check_overrender_callback, &overrender_data, &pf_clip);
  517.  
  518.     /* if not, do it the easy way */
  519.     if (overrender_data.mo_priority == priority)
  520.     {
  521.         atarigen_mo_draw_8x8_strip(bitmap, gfx, code, color, hflip, 0, xpos, ypos, vsize, clip, TRANSPARENCY_PEN, 0);
  522.     }
  523.  
  524.     /* otherwise, make it tricky */
  525.     else
  526.     {
  527.         /* draw an instance of the object in all transparent pens */
  528.         atarigen_mo_draw_transparent_8x8_strip(bitmap, gfx, code, hflip, 0, xpos, ypos, vsize, clip, TRANSPARENCY_PEN, 0);
  529.  
  530.         /* and then draw it normally on the temp bitmap */
  531.         atarigen_mo_draw_8x8_strip(atarigen_pf_overrender_bitmap, gfx, code, color, hflip, 0, xpos, ypos, vsize, clip, TRANSPARENCY_NONE, 0);
  532.  
  533.         /* overrender the playfield on top of that that */
  534.         overrender_data.mo_priority = priority;
  535.         overrender_data.bitmap = atarigen_pf_overrender_bitmap;
  536.         atarigen_pf_process(pf_overrender_callback, &overrender_data, &pf_clip);
  537.  
  538.         /* finally, copy this chunk to the real bitmap */
  539.         copybitmap(bitmap, atarigen_pf_overrender_bitmap, 0, 0, 0, 0, &pf_clip, TRANSPARENCY_THROUGH, palette_transparent_pen);
  540.     }
  541. }
  542.